
#include "RenderSystem.h"

#include <ALittleClient/ScheduleSystem/EventDefine.h>
#include <ALittleClient/ScriptSystem/ScriptSystem.h>
#include <ALittleClient/LogSystem/LogSystem.h>
#include <ALittleClient/RenderSystem/UISystem/UISystem.h>
#include <ALittleClient/RenderSystem/EntitySystem/EntitySystem.h>

namespace ALittle
{

RenderSystem::RenderSystem()
: m_context(0)
, m_window(0)
, m_width(800)
, m_height(600)
, m_title("Sail")
, m_fullscreen(false)
{ }

RenderSystem::~RenderSystem() {}

RenderSystem& RenderSystem::Instance()
{
	static RenderSystem instance;
	return instance;
}

void RenderSystem::Setup()
{
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

	unsigned int flag = 0;
	if (m_fullscreen) flag |= SDL_WINDOW_FULLSCREEN;
	flag |= SDL_WINDOW_RESIZABLE;
	flag |= SDL_WINDOW_OPENGL;
	m_window = SDL_CreateWindow(m_title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, flag);
	if (!m_window)
	{
		ALITTLE_ERROR("window create failed:multisample failed and recreate window without multisample.");

		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
		m_window = SDL_CreateWindow(m_title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, flag);

		ALITTLE_ERROR("window recreate failed:" << SDL_GetError());
		return;
	}
	m_context = SDL_GL_CreateContext(m_window);
	if (!m_context)
	{
		ALITTLE_ERROR(SDL_GetError());
		return;
	}

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glShadeModel(GL_SMOOTH);

	glViewport(0, 0, m_width, m_height);

	g_EntitySystem.Setup();
	g_UISystem.Setup();
}

void RenderSystem::Shutdown()
{
	g_EntitySystem.Shutdown();
	g_UISystem.Shutdown();

	if (m_context)
	{
		SDL_GL_DeleteContext(m_context);
		m_context = NULL;
	}

	if (m_window)
	{
		 SDL_DestroyWindow(m_window);
		 m_window = NULL;
	}
}

void RenderSystem::RegisterToScript()
{
	g_ScriptSystem.RegisterClass2Script<RenderSystem>("GlobalRenderSystem")
		.AddMemberFunction("SetWindowSize", &RenderSystem::SetWindowSize);

	g_ScriptSystem.SetValue("Global_RenderSystem", &g_RenderSystem);

	g_UISystem.RegisterToScript();
	g_EntitySystem.RegisterToScript();
}

void RenderSystem::Render()
{
	if (!m_context) return;

	glClear(GL_COLOR_BUFFER_BIT);

	glClear(GL_DEPTH_BUFFER_BIT);
	g_EntitySystem.Render();

	glClear(GL_DEPTH_BUFFER_BIT);
	g_UISystem.Render();

	SDL_GL_SwapWindow(m_window);
}

void RenderSystem::SetWindowSize(unsigned int width, unsigned int height)
{
	if (m_width == width && m_height == height) return;
	if (width == 0 || height == 0) return;

	m_width = width; m_height = height;

	if (!m_window) return;
	SDL_SetWindowSize(m_window, m_width, m_height);
}

void RenderSystem::HandleWindowResized(unsigned int width, unsigned int height)
{
	m_width = width;
	m_height = height;
	glViewport(0, 0, m_width, m_height);

	g_ScriptSystem.Invoke<void>("Global_Window_Resized", m_width, m_height);
}

unsigned int RenderSystem::GetWindowWidth() const
{
	return m_width;
}

unsigned int RenderSystem::GetWindowHeight() const
{
	return m_height;
}

} // ALittle
